package cn.iocoder.yudao.module.project.service.productprocesscompleted;

import cn.hutool.core.thread.ThreadUtil;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils;
import cn.iocoder.yudao.module.project.config.projectDefine;
import cn.iocoder.yudao.module.project.controller.admin.deptcompletedlog.vo.DeptCompletedLogSaveReqVO;
import cn.iocoder.yudao.module.project.controller.admin.internalcode.InternalCodeController;
import cn.iocoder.yudao.module.project.dal.dataobject.deptcompletedlog.DeptCompletedLogDO;
import cn.iocoder.yudao.module.project.dal.dataobject.dispatchlist.DispatchListDO;
import cn.iocoder.yudao.module.project.dal.dataobject.internalcode.InternalCodeDO;
import cn.iocoder.yudao.module.project.dal.dataobject.orderdetail.OrderDetailDO;
import cn.iocoder.yudao.module.project.dal.dataobject.productioncode.ProductionCodeDO;
import cn.iocoder.yudao.module.project.dal.dataobject.weighthistory.WeightHistoryDO;
import cn.iocoder.yudao.module.project.dal.dataobject.workstation.WorkstationDO;
import cn.iocoder.yudao.module.project.dal.mysql.deptcompletedlog.DeptCompletedLogMapper;
import cn.iocoder.yudao.module.project.dal.mysql.dispatchlist.DispatchListMapper;
import cn.iocoder.yudao.module.project.dal.mysql.internalcode.InternalCodeMapper;
import cn.iocoder.yudao.module.project.dal.mysql.order.OrderMapper;
import cn.iocoder.yudao.module.project.dal.mysql.productioncode.ProductionCodeMapper;
import cn.iocoder.yudao.module.project.dal.mysql.weighthistory.WeightHistoryMapper;
import cn.iocoder.yudao.module.project.dal.mysql.workstation.WorkstationMapper;
import cn.iocoder.yudao.module.project.service.deptcompletedlog.DeptCompletedLogService;
import cn.iocoder.yudao.module.project.service.internalworkstationplan.InternalWorkstationPlanService;
import cn.iocoder.yudao.module.project.service.orderdetail.OrderDetailService;
import cn.iocoder.yudao.module.project.service.workstation.WorkstationService;
import cn.iocoder.yudao.module.system.api.dept.DeptApi;
import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO;
import cn.iocoder.yudao.module.system.api.permission.PermissionApi;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.sun.corba.se.spi.orbutil.threadpool.Work;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import cn.iocoder.yudao.module.project.controller.admin.productprocesscompleted.vo.*;
import cn.iocoder.yudao.module.project.dal.dataobject.productprocesscompleted.ProductProcessCompletedDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;

import cn.iocoder.yudao.module.project.dal.mysql.productprocesscompleted.ProductProcessCompletedMapper;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.project.config.projectDefine.HTTP_STATUS.ERROR_STATUS_EXISTS;
import static cn.iocoder.yudao.module.project.config.projectDefine.HTTP_STATUS.ERROR_STATUS_LOGOUT;
import static cn.iocoder.yudao.module.project.enums.ErrorCodeConstants.*;

/**
 * 产品完成工序 Service 实现类
 *
 * @author 管理员
 */
@Service
@Validated
public class ProductProcessCompletedServiceImpl implements ProductProcessCompletedService {

    @Resource
    private ProductProcessCompletedMapper productProcessCompletedMapper;

    @Resource
    private InternalCodeMapper internalCodeMapper;


    @Resource
    private WeightHistoryMapper weightHistoryMapper;

    @Resource
    private WorkstationMapper workstationMapper;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Resource
    private DispatchListMapper dispatchListMapper;

    @Resource
    private WorkstationService workstationService;

    @Resource
    private PermissionApi permissionApi;

    @Resource
    private AdminUserApi adminUserApi;

    @Resource
    private DeptApi deptApi;

    @Resource
    private DeptCompletedLogService deptCompletedLogService;

    @Resource
    private DeptCompletedLogMapper deptCompletedLogMapper;

    @Resource
    private ProductionCodeMapper productionCodeMapper;

    @Resource
    private OrderDetailService orderDetailService;

    @Resource
    private InternalWorkstationPlanService internalWorkstationPlanService;

    @Override
    public Integer createProductProcessCompleted(ProductProcessCompletedSaveReqVO createReqVO) {
        // 插入
        ProductProcessCompletedDO productProcessCompleted = BeanUtils.toBean(createReqVO, ProductProcessCompletedDO.class);
        productProcessCompletedMapper.insert(productProcessCompleted);
        // 返回
        return productProcessCompleted.getId();
    }

    @Override
    public void updateProductProcessCompleted(ProductProcessCompletedSaveReqVO updateReqVO) {
        // 校验存在
        validateProductProcessCompletedExists(updateReqVO.getId());
        // 更新
        ProductProcessCompletedDO updateObj = BeanUtils.toBean(updateReqVO, ProductProcessCompletedDO.class);
        productProcessCompletedMapper.updateById(updateObj);
    }

    @Override
    public void deleteProductProcessCompleted(Integer id) {
        // 校验存在
        validateProductProcessCompletedExists(id);
        // 删除
        productProcessCompletedMapper.deleteById(id);
    }

    private void validateProductProcessCompletedExists(Integer id) {
        if (productProcessCompletedMapper.selectById(id) == null) {
            throw exception(PRODUCT_PROCESS_COMPLETED_NOT_EXISTS);
        }
    }

    @Override
    public ProductProcessCompletedDO getProductProcessCompleted(Integer id) {
        return productProcessCompletedMapper.selectById(id);
    }

    @Override
    public PageResult<ProductProcessCompletedDO> getProductProcessCompletedPage(ProductProcessCompletedPageReqVO pageReqVO) {
        Long loginUserId = WebFrameworkUtils.getLoginUserId();

        boolean adminFlag = permissionApi.hasAnyRoles(loginUserId, "longyi_admin");
        boolean managerFlag = permissionApi.hasAnyRoles(loginUserId, "longyi_manager");

        if(managerFlag || adminFlag){
            AdminUserRespDTO adminUserRespDTO = adminUserApi.getUser(loginUserId);
            Long deptId = adminUserRespDTO.getDeptId();
            pageReqVO.setDeptId(deptId.intValue());

            if(loginUserId == 150L){
                pageReqVO.setCreator(138L);
            }else if(loginUserId == 153L){
                pageReqVO.setCreator(149L);
            }
        }else{
            pageReqVO.setDeptId(-1);
        }

        return productProcessCompletedMapper.selectPage(pageReqVO);
    }

    @Override
    public void createProductProcessCompleted(String internalCode, Integer workstationId) {
        asyncCreateProductProcessCompleted(internalCode, workstationId);
    }

    @Transactional
    public Integer asyncCreateProductProcessCompleted(String internalCode, Integer workstationId) {
        InternalCodeDO internalCodeDO = internalCodeMapper.selectOne(InternalCodeDO::getId, internalCode);

        internalWorkstationPlanService.completeWorkstationPlan(internalCode, workstationId);

        String orderPrtID =  "" ;
        int index = internalCodeDO.getOrderDetailId().indexOf("_");
        if (index != -1) { // 确保找到了字符
            orderPrtID = internalCodeDO.getOrderDetailId().substring(index + 1);
        }
        OrderDetailDO orderDetail = orderDetailService.getOrderDetail(internalCodeDO.getOrderDetailId());

        Long loginUserId = SecurityFrameworkUtils.getLoginUserId();

        if(loginUserId == null){
            throw new ServiceException(ERROR_STATUS_LOGOUT, "登录信息已失效，请重新登录。");
        }

        stringRedisTemplate.opsForHash().put("CACHE_ORDER_CODE", String.valueOf(loginUserId), internalCodeDO.getOrderCode());

        String orderCode = internalCodeDO.getOrderCode();

        WorkstationDO workstationDO = workstationMapper.selectOne(WorkstationDO::getId, workstationId);
        Integer department = workstationDO.getDepartment();

        DictDataRespDTO dictDataRespDTO = workstationService.getWorkstationDept(department);
        String deptName = dictDataRespDTO.getLabel();

        QueryWrapper<WorkstationDO> workstationDOQueryWrapper = new QueryWrapper<>();
        workstationDOQueryWrapper.eq("department", department);
        workstationDOQueryWrapper.eq("is_control", 1);
        List<WorkstationDO> deptWorkstationDOList = workstationMapper.selectList(workstationDOQueryWrapper);

        List<Integer> deptProcessOrderList = deptWorkstationDOList.stream().map(item -> item.getProcessOrder()).collect(Collectors.toList());


        List<Integer> productWorkstationIdList = new ArrayList<>();

        List<WeightHistoryDO> weightHistoryDOList = weightHistoryMapper.selectList(WeightHistoryDO::getInternalCode, internalCode);
        if(null != weightHistoryDOList && weightHistoryDOList.size() > 0){
            for (WeightHistoryDO weightHistoryDO : weightHistoryDOList) {
                Integer weightWorkstationId = weightHistoryDO.getWeightWorkstationId();
                if (null != weightWorkstationId && !productWorkstationIdList.contains(weightWorkstationId)) {
                    productWorkstationIdList.add(weightWorkstationId);
                }
            }
        }


        Integer testWorkstationId = internalCodeDO.getTestWorkstationId();
        if (null != testWorkstationId && !productWorkstationIdList.contains(testWorkstationId)) {
            productWorkstationIdList.add(testWorkstationId);
        }

        Integer balanceTwiceWorkstationId = internalCodeDO.getBalanceTwiceWorkstationId();
        if (null != balanceTwiceWorkstationId && !productWorkstationIdList.contains(balanceTwiceWorkstationId)) {
            productWorkstationIdList.add(balanceTwiceWorkstationId);
        }

        List<ProductionCodeDO> productionCodeDOList = productionCodeMapper.selectList(ProductionCodeDO::getInternalCode, internalCode);
        if(null != productionCodeDOList && productionCodeDOList.size() > 0){
            for (ProductionCodeDO productionCodeDO : productionCodeDOList){
                if(null != productionCodeDO.getAssociatedWorkstationId()){
                    productWorkstationIdList.add(productionCodeDO.getAssociatedWorkstationId());
                }
            }
        }

        DictDataRespDTO dictDataRespDTOC = workstationService.getWorkstationDept("C课");
        Integer deptCId = Integer.parseInt(dictDataRespDTOC.getValue());
        List<WorkstationDO> deptCWorkstationDOList = workstationMapper.selectList(WorkstationDO::getDepartment, deptCId);

        boolean completed = true;

        if(productWorkstationIdList.size() > 0){

            boolean deptCFlag = false;
            for(WorkstationDO deptCWorkstationDO : deptCWorkstationDOList){
                if(productWorkstationIdList.contains(deptCWorkstationDO.getId())){
                    deptCFlag = true;
                    break;
                }
            }

            if(deptCFlag){
                DispatchListDO dispatchListDO = new DispatchListDO();
                dispatchListDO.setStatus(projectDefine.ORDER_STATUS.ORDER_STATUS_2);
                dispatchListMapper.update(dispatchListDO, new QueryWrapper<DispatchListDO>().eq("ticket_number", internalCodeDO.getOrderCode()));
            }



            List<WorkstationDO> workstationDOList = workstationMapper.selectList(new QueryWrapper<WorkstationDO>().in("id", productWorkstationIdList));
            List<Integer> productProcessOrderList = workstationDOList.stream().map(item -> item.getProcessOrder()).collect(Collectors.toList());

            for(Integer deptProcessOrder : deptProcessOrderList){
                if(!productProcessOrderList.contains(deptProcessOrder)){
                    completed = false;
                    break;
                }
            }
        }else{
            completed = false;
        }

        if(!completed){
            return null;
        }

        ProductProcessCompletedSaveReqVO productProcessCompletedSaveReqVO = new ProductProcessCompletedSaveReqVO();
        productProcessCompletedSaveReqVO.setDeptId(department);
        productProcessCompletedSaveReqVO.setInternalCode(internalCode);
        productProcessCompletedSaveReqVO.setDeliveryStatus("0");
        productProcessCompletedSaveReqVO.setDeptName(deptName);
        productProcessCompletedSaveReqVO.setLastCollectionTime(LocalDateTime.now());
        productProcessCompletedSaveReqVO.setOrderId(internalCodeDO.getOrderCode());
        productProcessCompletedSaveReqVO.setType(internalCodeDO.getType());
        productProcessCompletedSaveReqVO.setRemark(orderDetail.getFlex());
        productProcessCompletedSaveReqVO.setLen(orderDetail.getLen());

        DeptCompletedLogSaveReqVO deptCompletedLogSaveReqVO = BeanUtils.toBean(productProcessCompletedSaveReqVO, DeptCompletedLogSaveReqVO.class);
        deptCompletedLogSaveReqVO.setOrderCode(internalCodeDO.getOrderCode());
        deptCompletedLogService.createDeptCompletedLog(deptCompletedLogSaveReqVO);

        createProductProcessCompleted(productProcessCompletedSaveReqVO);

        List<InternalCodeDO> internalCodeDOList = internalCodeMapper.selectList(InternalCodeDO::getOrderCode, orderCode);

        boolean orderFinished = true;
        Set<String> internalIdSet = internalCodeDOList.stream().map(item -> item.getId()).collect(Collectors.toSet());

        List<ProductProcessCompletedDO> productProcessCompletedDOList = productProcessCompletedMapper.selectList(ProductProcessCompletedDO::getOrderId, orderCode);
        if(productProcessCompletedDOList != null && productProcessCompletedDOList.size() > 0){
            Set<String> completedInternalCodeSet = productProcessCompletedDOList.stream().map(item -> item.getInternalCode()).collect(Collectors.toSet());

            internalIdSet.retainAll(completedInternalCodeSet);
            if(internalIdSet.size() > 0){
                orderFinished = false;
            }
        }

        if(orderFinished){
            DispatchListDO dispatchListDO = new DispatchListDO();
            dispatchListDO.setStatus(projectDefine.ORDER_STATUS.ORDER_STATUS_3);
            dispatchListMapper.update(dispatchListDO, new QueryWrapper<DispatchListDO>().eq("ticket_number", internalCodeDO.getOrderCode()));
        }

        return productProcessCompletedSaveReqVO.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteProductProcessCompletedByInternalCode(String internalCode, Integer deptId) {
        QueryWrapper<ProductProcessCompletedDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("internal_code", internalCode);
        queryWrapper.eq("dept_id", deptId);
        productProcessCompletedMapper.delete(queryWrapper);

        QueryWrapper<DeptCompletedLogDO> completedDOQueryWrapper = new QueryWrapper<>();
        completedDOQueryWrapper.eq("internal_code", internalCode);
        completedDOQueryWrapper.eq("dept_id", deptId);
        deptCompletedLogMapper.delete(completedDOQueryWrapper);
    }
}